# tests for Task class

import datetime

from libTodotxt import Task

base = {
        'completed' :False,
        'dtCompleted' :None,
        'priority' :None,
        'dtCreated' :datetime.date.today(),
        'text' :'',
        'projects' :[],
        'contexts' :[],
        'fromString': None,
        'toString': None,
        'id': -1
        }

def test_TaskInstantiation_noarg():
    """verify that the task exposes the proper attributes and defaults"""
    task = Task()
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == datetime.date.today()
    assert task.text == ''
    assert task.projects == []
    assert task.contexts == []

def test_TaskAttrs():
    task = Task()
    for a in dir(task):
        if not a.startswith('_'):  #skip single and dunder private methods/attrs
            assert a in base

def test_TaskAttrsInverse():
    task = Task()
    #verify the reverse
    for a in base:
        assert a in dir(task)

def test_TaskInitFullCompleted():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "x 2012-03-20 (A) 2012-03-20 My Lovely task +shamoo @home"
    task = Task(s)
    assert task.completed == True
    assert task.dtCompleted == datetime.date(2012,3,20)
    assert task.priority == 'A'
    assert task.dtCreated == datetime.date(2012,3,20)
    assert task.text == 'My Lovely task +shamoo @home'
    assert task.projects == ['+shamoo']
    assert task.contexts == ['@home']

def test_TaskInitFullCompleted3Projects():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "x 2012-03-20 (A) 2012-03-20 My Lovely task +shamoo +fulcrum +redstone @home"
    task = Task(s)
    assert task.completed == True
    assert task.dtCompleted == datetime.date(2012,3,20)
    assert task.priority == 'A'
    assert task.dtCreated == datetime.date(2012,3,20)
    assert task.text == 'My Lovely task +shamoo +fulcrum +redstone @home'
    assert task.projects == ['+shamoo','+fulcrum','+redstone']
    assert task.contexts == ['@home']

def test_TaskInitFullCompleted3Contexts():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "x 2012-03-20 (A) 2012-03-20 My Lovely task +shamoo @home @work @sleep"
    task = Task(s)
    assert task.completed == True
    assert task.dtCompleted == datetime.date(2012,3,20)
    assert task.priority == 'A'
    assert task.dtCreated == datetime.date(2012,3,20)
    assert task.text == 'My Lovely task +shamoo @home @work @sleep'
    assert task.projects == ['+shamoo']
    assert task.contexts == ['@home','@work','@sleep']

def test_TaskInitFullCompleted3Projects3Contexts():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "x 2012-03-20 (A) 2012-03-20 My @home Lovely +shamoo task +fulcrum +redstone @work @sleep"
    task = Task(s)
    assert task.completed == True
    assert task.dtCompleted == datetime.date(2012,3,20)
    assert task.priority == 'A'
    assert task.dtCreated == datetime.date(2012,3,20)
    assert task.text == 'My @home Lovely +shamoo task +fulcrum +redstone @work @sleep'
    assert task.projects == ['+shamoo','+fulcrum','+redstone']
    assert task.contexts == ['@home','@work','@sleep']

def test_TaskInitFullUncompleted():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "(A) 2012-03-20 My Lovely task +shamoo @home"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == 'A'
    assert task.dtCreated == datetime.date(2012,3,20)
    assert task.text == 'My Lovely task +shamoo @home'
    assert task.projects == ['+shamoo']
    assert task.contexts == ['@home']


def test_TaskInitPartialUncompleted():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "(A) My Lovely task +shamoo @home"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == 'A'
    assert task.dtCreated == None
    assert task.text == 'My Lovely task +shamoo @home'
    assert task.projects == ['+shamoo']
    assert task.contexts == ['@home']

def test_TaskInitPartial2Uncompleted():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "2012-03-20 My Lovely task +shamoo @home"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == datetime.date(2012,3,20)
    assert task.text == 'My Lovely task +shamoo @home'
    assert task.projects == ['+shamoo']
    assert task.contexts == ['@home']

def test_TaskInitPartial3Uncompleted():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "My Lovely task +shamoo @home"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == None
    assert task.text == 'My Lovely task +shamoo @home'
    assert task.projects == ['+shamoo']
    assert task.contexts == ['@home']

def test_TaskInitPartial3UncompletedNoProjects():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "My Lovely task @home"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == None
    assert task.text == 'My Lovely task @home'
    assert task.projects == []
    assert task.contexts == ['@home']

def test_TaskInitPartial3UncompletedNoContexts():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "My Lovely task +shamoo"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == None
    assert task.text == 'My Lovely task +shamoo'
    assert task.projects == ['+shamoo']
    assert task.contexts == []

def test_TaskInitPartial3UncompletedNoProjectsNoContexts():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "My Lovely task"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == None
    assert task.text == 'My Lovely task'
    assert task.projects == []
    assert task.contexts == []

def test_TaskInitPartial3UncompletedNoProjectsNoContextsTricky():
    #[*complete_flag* *completed_date* ][(*pri*) ][*creation_date* ]Task specific text on one line with both [*project* ] and [*context* ]intermingled with in the task text
    s = "x marks the spot, +HideTreasure @deserted_island"
    task = Task(s)
    assert task.completed == False
    assert task.dtCompleted == None
    assert task.priority == None
    assert task.dtCreated == None
    assert task.text == 'x marks the spot, +HideTreasure @deserted_island'
    assert task.projects == ['+HideTreasure',]
    assert task.contexts == ['@deserted_island',]

# New since 2012-03 March meeting
def test_TasktoString():
    taskList=[
        '(A) Thank Mom for the meatballs @phone',
        '(B) Schedule Goodwill pickup +GarageSale @phone',
        'Post signs around the neighborhood +GarageSale',
        '@GroceryStore Eskimo pies'
       ]
    for tstring in taskList:
        task = Task(tstring)
        assert tstring == task.toString()

def test_TaskWithEmailAddress():
    s = "Email Steve steve@domain.com about project FooBar +email @email"
    task = Task(s)
    assert task.contexts == ['@email']
    assert s == task.text

def test_markAsCompletedUpdatesdtCompleted():
    """marking a task completed, updates .dtCompleted to today's date"""
    task = Task('my task')
    task.completed = True
    assert task.dtCompleted == datetime.date.today()

def test_markAsNotCompletedUpdatesdtCompleted():
    """marking a task not completed, updates .dtCompleted to None"""
    task = Task('x 2012-03-30 my task')
    task.completed = False
    assert task.dtCompleted is None

def test_invalidDateCompleted():
    """if completed requires x and a date, then an invalid date should make the entire thing not completed"""
    task = Task('x 2011-04-31 my task')  #30 days has sept, april, jun and nov
    assert task.completed == False
    assert task.dtCompleted is None

def test_priorityASortBeforePriorityB():
    """a task with Priority A is more than the same with a (B)"""
    taskA = Task('(A) pet dog')
    taskB = Task('(B) pet dog')
    assert taskA < taskB
    assert not taskA > taskB
    assert sorted([taskB, taskA]) == [taskA, taskB]

def test_priorityASortBeforeNoPriority():
    """a task with Priority A is more than the same without a priority"""
    taskA = Task('(A) pet dog')
    taskB = Task('pet dog')
    assert taskA < taskB
    assert not taskA > taskB
    assert sorted([taskB, taskA]) == [taskA, taskB]

def test_invalidPriorityInit():
    """a task with Priority 'a' is not a real priority 'A'"""
    task = Task('(a) pet dog')
    assert task.priority is None

def test_invalidPrioritySet():
    """setting a task to a Priority of 'a' should not work"""
    task = Task('pet dog')
    try:
        task.priority = 'a'
        assert False
    except ValueError:
        assert True

def test_fakeProjects():
    ''' try sticking a bunch of + looking but not real projects in the task string'''
    task = Task('pet dog + +1 +2  1+2=3 +foo +foo+bar')
    assert task.projects == ['+1', '+2', '+foo', '+foo+bar']

def test_fakeContexts():
    ''' try sticking a bunch of @ looking but not real contexts in the task string'''
    task = Task('pet dog @ @1 @2  1@2=3 tom@thumb.com @foo @foo@bar')
    assert task.contexts == ['@1', '@2', '@foo', '@foo@bar']